package net.holmconsulting.database.server.plugin;

import java.io.File;
import java.io.PrintWriter;
import java.util.ResourceBundle;

import net.holmconsulting.database.server.plugin.preferences.PreferenceConstants;
import net.holmconsulting.database.server.plugin.views.ServerView;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.hsqldb.persist.HsqlProperties;
import org.hsqldb.server.Server;
import org.hsqldb.server.ServerConstants;
import org.osgi.framework.BundleContext;


/**
 * The activator class controls the plug-in life cycle
 */
public class Activator extends AbstractUIPlugin {

	// The plug-in ID
	public static final String PLUGIN_ID = "net.holmconsulting.database.server.plugin"; //$NON-NLS-1$

	// The shared instance
	private static Activator plugin;
	
	// Locale Specific Resource Bundle
			private static final ResourceBundle BUNDLE = ResourceBundle
					.getBundle("i18n.Resources");
	
	// The server
	private Server server;
	
	/**
	 * The constructor
	 */
	public Activator() {
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
	 */
	public void start(BundleContext context) throws Exception {
		super.start(context);
		plugin = this;
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext context) throws Exception {
		// Get Persist Preference
		boolean persist = plugin.getPreferenceStore().getBoolean(
				PreferenceConstants.PARAM_PERSIST);		 

		if (server != null) {
			Activator.getDefault().stopServer();
		}

		// If not persisting, delete all messages
		if (!persist) {
			IPreferenceStore store = Activator.getDefault().getPreferenceStore();
			File rootDir = Activator.getDefault().getStateLocation().toFile();
		    String fileName = store.getString(PreferenceConstants.PARAM_DATABASE_FILE_STORE);
		    final File databaseFile = new File(rootDir, fileName);
		    Runnable runnable = new Runnable() {
		    	public void run() {
		    	  while (server != null &&  (server.getState() == ServerConstants.SERVER_STATE_ONLINE || server.getState() == ServerConstants.SERVER_STATE_OPENING )) {
		    		  try {
		    			  Thread.sleep(1000);
		    		  }catch(InterruptedException ex) {
		    			  
		    		  }
		    	  } // while
		    	  
		    	  int counter = 10;
		    	  boolean success = databaseFile.delete();
		    	  while(counter >0 &&  !success) {
		    		   success = databaseFile.delete();
		    		  try {
		    			  counter--;
		    			  Thread.sleep(1000);
		    		  }catch(InterruptedException ex) {
		    			  
		    		  }
		    	  }
		    	  
		    	  if(success) {
		    		  System.out.println("databbase file store has been deleted successfully");  
		    	  }else {
		    		  System.out.println("databbase file store has not  been deleted");
		    	  }
		    	  
		    	  
		    	}
		    };
		 
		    runnable.run();
		    
	    }
		
		
		
		plugin = null;
		super.stop(context);
	}

	/**
	 * Returns the shared instance
	 *
	 * @return the shared instance
	 */
	public static Activator getDefault() {
		return plugin;
	}
	
	/**
	 * Returns the resource bundle
	 * @return the resource bundle
	 */
	public static ResourceBundle getResourceBundle() {
		return BUNDLE;
	}

	/**
	 * Returns an image descriptor for the image file at the given
	 * plug-in relative path
	 *
	 * @param path the path
	 * @return the image descriptor
	 */
	public static ImageDescriptor getImageDescriptor(String path) {
		return imageDescriptorFromPlugin(PLUGIN_ID, path);
	}
	
	
	/**
	 * Creates a new ThreadGroup for the FTP Server.
	 */
	public void startServer() {
		IPreferenceStore store = Activator.getDefault().getPreferenceStore();
		// default root directory always 
		File rootDir = Activator.getDefault().getStateLocation().toFile();
		
		String databaseName =  store.getString(PreferenceConstants.PARAM_DATABASE_NAME);
		String fileName = store.getString(PreferenceConstants.PARAM_DATABASE_FILE_STORE);
		
		// set up the rest of properties
		 server = new Server();
		
		Runnable runnable = new ServerStarter(server, rootDir, fileName, databaseName);
		
        ThreadGroup tg = new ServerThreadGroup("Server");
	
        
		
		new Thread(tg, runnable).start();

		
	}
	
	
	private static class  ServerStarter implements Runnable {
		private Server server;
		private File rootDir;
		private  String fileName;
		private String databaseName;
		
		public ServerStarter(Server server, File rootDir, String fileName, String databaseName) {
			super();
			this.server = server;
			this.rootDir = rootDir;
			this.fileName = fileName;
			this.databaseName = databaseName;
		}



		public void run() {
			File databaseFile = new File(rootDir, fileName);
			String databaseFileAbsPath = databaseFile.getAbsolutePath();
			System.out.println("database location-->" + databaseFileAbsPath);
			HsqlProperties p = new HsqlProperties();
			p.setProperty("server.database.0", "file:" + databaseFileAbsPath);
			p.setProperty("server.dbname.0", databaseName);
			
			try {
				server.setProperties(p);
				File dblogFile = new File(rootDir, "database.log");
				PrintWriter dbServerWriter = new PrintWriter(dblogFile);
				server.setLogWriter(dbServerWriter); // can use custom writer
				server.setErrWriter(dbServerWriter); // can use custom writer
				server.start();
				while(true ) {
					if(server.getState() != ServerConstants.SERVER_STATE_ONLINE) {
						Thread.sleep(500);	
					}else {
						 
						 Display.getDefault().syncExec(new Runnable() {
								public void run() {
									ServerView view = (ServerView) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(ServerView.ID);
									view.disableStartServer();
									view.enableStopServer();
									System.out.println("HSQLD server is running now");
								}
							});
						
					  break;
					}
					
				}
			}catch(Exception ex) {
				throw new RuntimeException(ex);
			}

		} // run
		
	} // ServerStarter
	
	
	public void stopServer() {
		Runnable runnable = new ServerStopper(server);
		ThreadGroup tg = new ServerThreadGroup("Server");
	    new Thread(tg, runnable).start();
	}
	
	
 private static class ServerStopper implements Runnable {
	 private Server server;
	 private boolean stopped;
	 public ServerStopper(Server server) {
		 this.server = server;
	 }
	 
     public void  run() {
    	 if(server != null &&  (server.getState() == ServerConstants.SERVER_STATE_ONLINE || server.getState() == ServerConstants.SERVER_STATE_OPENING )) {
 			server.shutdown();
 			stopped = true;
 		 }
    	 
    	 while(stopped && (server.getState() != ServerConstants.SERVER_STATE_SHUTDOWN && server.getState() != ServerConstants.SERVER_STATE_CLOSING)) {
    		 try {
    		   Thread.sleep(500);
    		 }catch(InterruptedException ex) {
    			 
    		 }
    	 }
    	 
    	if(stopped) {
    		Display.getDefault().syncExec(new Runnable() {
    			public void run() {
					ServerView view = (ServerView) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(ServerView.ID);
					 if(view == null) {
						System.out.println("view is nulll; it seems the gui is not present any more..");
						 return ;
					 }
					view.disableStopServer();
					view.enableStartServer();
					System.out.println("HSQLD server has stopped");
				}
			});
       }
        	 
     }
 }
	
	
	 /**
	    * It is only used by this class; no need to reference instance variable
	    * 
	    * @author alan mehio
	    *
	    */
	   private static  class ServerThreadGroup extends ThreadGroup {

			public ServerThreadGroup(String name) {
				super(name);
				
			}
			
			@Override
			public void uncaughtException(Thread t, final Throwable e) {
				Display.getDefault().asyncExec(new Runnable() {
					public void run() {

						ServerView view = (ServerView) PlatformUI.getWorkbench()
								.getActiveWorkbenchWindow().getActivePage()
								.findView(ServerView.ID);

						view.disableStopServer();
						view.enableStartServer();
	                  
							IStatus status = new Status(
									IStatus.ERROR,
									Activator.PLUGIN_ID,
									"The application has thrown an exception; please report to alan.mehio@gmail.com",
									e);

							ResourceBundle bundle = Activator.getResourceBundle();

							ErrorDialog.openError(view.getViewer().getControl()
									.getShell(), null, String.format(
									bundle.getString("exception.other"), ""),
									status);
						
					}
				});

		 }
			
	   } // AServerThreadGroup class
}
